#include "vtor_printf.h"

#ifdef __VTOR_PRINTF__

#if 0
int16_t VtorString_Printf(const char *format, ...)
{
	// https://blog.csdn.net/qq_32108893/article/details/78682531
	uint8_t str[128] = {'\0'}; 
	va_list ap;
	va_start(ap, format);
	vsprintf((char *)str, format, ap);
	va_end(ap);
	return VtorString_Print(str);
}
#endif


#if 0
//加入以下代码,支持printf函数,而不需要选择use MicroLIB
#pragma import(__use_no_semihosting)
//标准库需要的支持函数
struct __FILE
{
	int handle; 
};

FILE __stdout;
//定义_sys_exit()以避免使用半主机模式
void _sys_exit(int x)
{
	x = x;
}

//重定义fputc函数
int fputc(int ch, FILE *f)
{
	while((USART1->SR&0X40)==0){};//循环发送,直到发送完毕
	USART1->DR = (uint8_t) ch;
	return ch;
}
#endif 


uint8_t* VtorString_AlignMemory(uint8_t* base, int8_t typeSize)
{
    // 计算当前地址与 typeSize 的最近整数倍之间的差值
    int alignment = (int)base % typeSize;
    if (alignment != 0) {
        // 如果当前地址不是 typeSize 的整数倍，则增加到下一个整数倍
        // (typeSize - alignment) 计算出需要增加的字节数
        base += typeSize - alignment;
    }
	return base;
}

int16_t VtorSprintf(uint8_t* str, uint8_t* format, ...)
{
	uint32_t ch = 0; // 输出通道，默认printf使用0
	// 根据入参str是否为NULL，决定直接打印还是存储在字符串内
	uint8_t innerTempBuffer[VTOR_SPRINTF_BUFFER_SIZE] = { '\0' };
	if((uint32_t)str < 0xff) // 允许0xff个不同的输出渠道
	{
		// 如果走特殊通道，那么调整str指针
		str = innerTempBuffer;
		ch = (uint32_t)str;
	}

	uint8_t* buf = str;
	uint8_t* fmt = (uint8_t*)format;
	uint8_t* arg = (uint8_t*)((int32_t*)&format + 1);

	VtorString_Clear(buf);
	while (*fmt)
	{
		if(*fmt == '%')
		{
			switch (*(fmt + 1))
			{
			case 'x':
			case 'd':
				// 栈内元素需要对齐，int，string向上增长，对4对齐
				arg = VtorString_AlignMemory(arg, 4);
				if(*(fmt + 1) == 'd')
				{
					buf = VtorString_AppendInt(buf, *(int*)arg);
				}
				else
				{
					buf = VtorString_AppendHex(buf, *(int*)arg);
				}
				arg += 4;
			break;
			case 'f':
				arg = VtorString_AlignMemory(arg, 8);
				buf = VtorString_AppendFloat(buf, *(double*)arg);
				arg += 8;
			break;
			case 's':
				arg = VtorString_AlignMemory(arg, 4);
				buf = VtorString_AppendString(buf, (uint8_t*)((*(int*)arg)));
				arg += 4;
			break;
			default:
				
			break;
			}
			fmt += 2; // 跳过 百分号  和 格式控制符号
		}
		else
		{
			*buf = *fmt;
			buf++;
			fmt++;
		}
	}
	*buf = '\0';

	// 如果使用了前0xff个特殊通道，那么通过通道打印
	if(str == innerTempBuffer)
	{
		return VtorString_ChanPrintBuffer(ch , str, buf - str);
	}
	// 反之，如果使用了内存，那么直接放在内存即可，不需要其他任何操作
	return buf - str;
}

#endif // __VTOR_PRINTF__



